{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Tce3stUlHN0L"
      },
      "source": [
        "##### Copyright 2020 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "tuOe1ymfHZPu"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qFdPvlXBOdUN"
      },
      "source": [
        "# Keras Tuner の基礎"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MfBg1C5NB3X0"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "<img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\"><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ja/tutorials/keras/keras_tuner.ipynb\">TensorFlow.org で表示</a>\n",
        "</td>\n",
        "  <td>\n",
        "<img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\"><a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ja/tutorials/keras/keras_tuner.ipynb\">Google Colab で実行</a>\n",
        "</td>\n",
        "  <td>\n",
        "<img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\"><a target=\"_blank\" href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ja/tutorials/keras/keras_tuner.ipynb\">GitHub でソースを表示</a>\n",
        "</td>\n",
        "  <td>\n",
        "<img src=\"https://www.tensorflow.org/images/download_logo_32px.png\"><a href=\"https://storage.googleapis.com/tensorflow_docs/docs/site/en/tutorials/keras/keras_tuner.ipynb\">ノートブックをダウンロード</a>\n",
        "</td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xHxb-dlhMIzW"
      },
      "source": [
        "## 概要\n",
        "\n",
        "Keras Tuner は、TensorFlow プログラム向けに最適なハイパーパラメータを選択するためのライブラリです。ユーザーの機械学習（ML）アプリケーションに適切なハイパーパラメータを選択するためのプロセスは、*ハイパーパラメータチューニング*または*ハイパーチューニング*と呼ばれます。\n",
        "\n",
        "ハイパーパラメータは、ML のトレーニングプロセスとトポロジーを管理する変数です。これらの変数はトレーニングプロセス中、一貫して定数を維持し、ML プログラムのパフォーマンスに直接影響を与えます。ハイパーパラメータには、以下の 2 種類があります。\n",
        "\n",
        "1. **モデルハイパーパラメータ**: 非表示レイヤーの数と幅などのモデルの選択に影響します。\n",
        "2. **アルゴリズムハイパーパラメータ**: 確率的勾配降下法（SGD）の学習速度や k 最近傍（KNN）分類器の最近傍の数など、学習アルゴリズムの速度と質に影響します。\n",
        "\n",
        "このチュートリアルでは、Keras Tuner をし米須ヒデ、画像分類アプリケーションのハイパーチューニングを実施します。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MUXex9ctTuDB"
      },
      "source": [
        "## セットアップ"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "IqR2PQG4ZaZ0"
      },
      "outputs": [],
      "source": [
        "import tensorflow as tf\n",
        "from tensorflow import keras\n",
        "\n",
        "import IPython"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "g83Lwsy-Aq2_"
      },
      "source": [
        "Keras Tuner をインストールしてインポートします。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "_leAIdFKAxAD"
      },
      "outputs": [],
      "source": [
        "!pip install -U keras-tuner\n",
        "import kerastuner as kt"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ReV_UXOgCZvx"
      },
      "source": [
        "## データセットをダウンロードして準備する\n",
        "\n",
        "このチュートリアルでは、Keras Tuner を使用して、[Fashion MNIST データセット](https://github.com/zalandoresearch/fashion-mnist)の服飾の画像を分類する学習モデル向けに最適なハイパーパラメータを見つけます。 "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HljH_ENLEdHa"
      },
      "source": [
        "データを読み込みます。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "OHlHs9Wj_PUM"
      },
      "outputs": [],
      "source": [
        "(img_train, label_train), (img_test, label_test) = keras.datasets.fashion_mnist.load_data()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "bLVhXs3xrUD0"
      },
      "outputs": [],
      "source": [
        "# Normalize pixel values between 0 and 1\n",
        "img_train = img_train.astype('float32') / 255.0\n",
        "img_test = img_test.astype('float32') / 255.0"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "K5YEL2H2Ax3e"
      },
      "source": [
        "## モデルを定義する\n",
        "\n",
        "ハイパーチューニングを行うモデルを構築する際、モデルアーキテクチャのほかにハイパーパラメータ検索空間も定義します。ハイパーチューニング用にセットアップするモデルを*ハイパーモデル*と呼びます。\n",
        "\n",
        "ハイパーモデルの定義は、以下の 2 つの方法で行います。\n",
        "\n",
        "- モデルビルダー関数を使用する\n",
        "- Keras Tuner API の `HyperModel` クラスをサブクラス化する\n",
        "\n",
        "また、コンピュータビジョンアプリケーション用の [HyperXception](https://keras-team.github.io/keras-tuner/documentation/hypermodels/#hyperresnet-class) と <a>HyperResNet</a> という 2 つの事前定義済みの <code>HyperModel</code> クラスも使用します。\n",
        "\n",
        "このチュートリアルでは、モデルビルダー関数を使用して、画像分類モデルを定義します。モデルビルダー関数は、コンパイル済みのモデルを返し、インラインで定義するハイパーパラメータを使用してモデルをハイパーチューニングします。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ZQKodC-jtsva"
      },
      "outputs": [],
      "source": [
        "def model_builder(hp):\n",
        "  model = keras.Sequential()\n",
        "  model.add(keras.layers.Flatten(input_shape=(28, 28)))\n",
        "  \n",
        "  # Tune the number of units in the first Dense layer\n",
        "  # Choose an optimal value between 32-512\n",
        "  hp_units = hp.Int('units', min_value = 32, max_value = 512, step = 32)\n",
        "  model.add(keras.layers.Dense(units = hp_units, activation = 'relu'))\n",
        "  model.add(keras.layers.Dense(10))\n",
        "\n",
        "  # Tune the learning rate for the optimizer \n",
        "  # Choose an optimal value from 0.01, 0.001, or 0.0001\n",
        "  hp_learning_rate = hp.Choice('learning_rate', values = [1e-2, 1e-3, 1e-4]) \n",
        "  \n",
        "  model.compile(optimizer = keras.optimizers.Adam(learning_rate = hp_learning_rate),\n",
        "                loss = keras.losses.SparseCategoricalCrossentropy(from_logits = True), \n",
        "                metrics = ['accuracy'])\n",
        "  \n",
        "  return model"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0J1VYw4q3x0b"
      },
      "source": [
        "## チューナーをインスタンス化してハイパーチューニングを実行する\n",
        "\n",
        "チューナーをインスタンス化して、ハイパーチューニングを実行します。Keras Tuner には、`RandomSearch`、`Hyperband`、`BayesianOptimization`、および `Sklearn` チューナーがあります。このチュートリアルでは、[Hyperband](https://arxiv.org/pdf/1603.06560.pdf) チューナーを使用します。\n",
        "\n",
        "Hyperband チューナーをインスタンス化するには、ハイパーモデル、最適化する `objective`、およびトレーニングするエポックの最大数（`max_epochs`）を指定する必要があります。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "oichQFly6Y46"
      },
      "outputs": [],
      "source": [
        "tuner = kt.Hyperband(model_builder,\n",
        "                     objective = 'val_accuracy', \n",
        "                     max_epochs = 10,\n",
        "                     factor = 3,\n",
        "                     directory = 'my_dir',\n",
        "                     project_name = 'intro_to_kt') "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VaIhhdKf9VtI"
      },
      "source": [
        "Hyperband チューニングアルゴリズムは、適応型リソース割り当てと早期停止を使用して、高パフォーマンスモデルに素早く収束させます。これは、トーナメント式のツリーを使用して行われます。アルゴリズムは、数回のエポックで大量のモデルをトレーニングし、性能の高い上位半数のモデル次のラウンドに持ち越します。Hyperband は、1 + log<sub><code>factor</code></sub>(`max_epochs`) を計算し、直近の整数に繰り上げて、トーナメントでトレーニングするモデル数を決定します。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "oTeamrUWOJRb"
      },
      "source": [
        "ハイパーパラメータ検索を実行する前に、トレーニングステップごとにトレーニング出力をクリアにするコールバックを定義します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Bbr_8QE76PJd"
      },
      "outputs": [],
      "source": [
        "class ClearTrainingOutput(tf.keras.callbacks.Callback):\n",
        "  def on_train_end(*args, **kwargs):\n",
        "    IPython.display.clear_output(wait = True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "UKghEo15Tduy"
      },
      "source": [
        "ハイパーパラメータ検索を実行します。検索メソッドの引数は、上記のコールバックのほか、`tf.keras.model.fit` に使用される引数と同じです。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "dSBQcTHF9cKt"
      },
      "outputs": [],
      "source": [
        "tuner.search(img_train, label_train, epochs = 10, validation_data = (img_test, label_test), callbacks = [ClearTrainingOutput()])\n",
        "\n",
        "# Get the optimal hyperparameters\n",
        "best_hps = tuner.get_best_hyperparameters(num_trials = 1)[0]\n",
        "\n",
        "print(f\"\"\"\n",
        "The hyperparameter search is complete. The optimal number of units in the first densely-connected\n",
        "layer is {best_hps.get('units')} and the optimal learning rate for the optimizer\n",
        "is {best_hps.get('learning_rate')}.\n",
        "\"\"\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Lak_ylf88xBv"
      },
      "source": [
        "このチュートリアルの最後のステップとして、検索から得た最適なハイパーパラメータでモデルを保存します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "McO82AXOuxXh"
      },
      "outputs": [],
      "source": [
        "# Build the model with the optimal hyperparameters and train it on the data\n",
        "model = tuner.hypermodel.build(best_hps)\n",
        "model.fit(img_train, label_train, epochs = 10, validation_data = (img_test, label_test))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "EQRpPHZsz-eC"
      },
      "source": [
        "`my_dir/intro_to_kt` ディレクトリには、ハイパーパラメータ検索中に実行された各トライアル（モデル構成）の詳細なログとチェックポイントが含まれます。ハイパーパラメータ検索を再実行する場合、Keras Tuner は、これらのログの既存の状態を使用して、検索を再開します。この動作を無効にするには、チューナーをインスタンス化する際に、`overwrite = True` 引数を追加で渡してください。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sKwLOzKpFGAj"
      },
      "source": [
        "## まとめ\n",
        "\n",
        "このチュートリアルでは、Keras Tuner の使用して、モデルのハイパーパラメータを調整する方法を学習しました。Keras Tuner の調査委については、以下のその他のリソースをご覧ください。\n",
        "\n",
        "- [TensorFlow ブログの Keras Tuner 関連記事](https://blog.tensorflow.org/2020/01/hyperparameter-tuning-with-keras-tuner.html)\n",
        "- [Keras Tuner ウェブサイト](https://keras-team.github.io/keras-tuner/)\n",
        "\n",
        "また、モデルのハイパーパラメータを対話式で調整できる、TensorBoard の [HParams Dashboard](https://www.tensorflow.org/tensorboard/hyperparameter_tuning_with_hparams) もご覧ください。"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [
        "Tce3stUlHN0L"
      ],
      "name": "keras_tuner.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
